/*
    Copyright (C) 2012 Lucas Paradisi, FuDePAN

    This file is part of Biopp.

    Biopp is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Biopp is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Biopp.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "biopp/biopp.h"

using namespace biopp;
using ::testing::Return;
using ::testing::ReturnRef;

struct Person
{
    size_t id;
    string name;

    Person(size_t Id, const string& Name)
        : id(Id), name(Name)
    {}
};

template <class T>
class MockIterator : public IteratorInterface<T>
{
public:
    MOCK_METHOD0_T(restart, void());
    MOCK_CONST_METHOD0_T(end, bool());
    MOCK_METHOD0_T(next, void());
    MOCK_METHOD0_T(endOfUse, void());
    MOCK_CONST_METHOD0_T(get, const T & ());
    MOCK_CONST_METHOD0_T(clone, IteratorInterface<T>* ());
    MOCK_METHOD0_T(count, size_t());
};

class IteratorTest : public ::testing::Test
{
protected:
    MockIterator<Person> mockedIteratorInterface;
    Iterator<Person> it;

    virtual void SetUp()
    {
        it = &mockedIteratorInterface;
    }
    virtual void TearDown()
    {
        EXPECT_CALL(mockedIteratorInterface, endOfUse())
        .Times(1);
    }
};


TEST_F(IteratorTest, restarting)
{
    EXPECT_CALL(mockedIteratorInterface, restart())
    .Times(1);

    it.restart();
}

TEST_F(IteratorTest, askingForTheEnd)
{
    EXPECT_CALL(mockedIteratorInterface, end())
    .Times(1);
    ON_CALL(mockedIteratorInterface, end())
    .WillByDefault(Return(true));

    it.end();
}

TEST_F(IteratorTest, usingNext)
{
    EXPECT_CALL(mockedIteratorInterface, next())
    .Times(1);

    it.next();
}

TEST_F(IteratorTest, usingOperatorPlusPlus)
{
    EXPECT_CALL(mockedIteratorInterface, next())
    .Times(1);

    ++it;
}

TEST_F(IteratorTest, gettingValue)
{
    const Person returnValue(1, "Carl");

    EXPECT_CALL(mockedIteratorInterface, get())
    .Times(1);
    ON_CALL(mockedIteratorInterface, get())
    .WillByDefault(ReturnRef(returnValue));

    *it;
}

TEST_F(IteratorTest, gettingValueInsideOfStruct)
{
    const Person returnValue(1, "Carl");

    EXPECT_CALL(mockedIteratorInterface, get())
    .Times(1);
    ON_CALL(mockedIteratorInterface, get())
    .WillByDefault(ReturnRef(returnValue));

    it->id;
}

TEST_F(IteratorTest, countingValues)
{
    EXPECT_CALL(mockedIteratorInterface, count())
    .Times(1);

    it.count();
}

TEST_F(IteratorTest, cloning)
{
    EXPECT_CALL(mockedIteratorInterface, clone())
    .Times(1);

    it.clone();
}